///*
// *  Copyright 2009-2016 Weibo, Inc.
// *
// *    Licensed under the Apache License, Version 2.0 (the "License");
// *    you may not use this file except in compliance with the License.
// *    You may obtain a copy of the License at
// *
// *        http://www.apache.org/licenses/LICENSE-2.0
// *
// *    Unless required by applicable law or agreed to in writing, software
// *    distributed under the License is distributed on an "AS IS" BASIS,
// *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// *    See the License for the specific language governing permissions and
// *    limitations under the License.
// */
//
//package cn.huwhy.bees.protocol.support;
//
//import java.util.ArrayList;
//import java.util.Collections;
//import java.util.List;
//
//import org.apache.commons.lang3.StringUtils;
//
//import cn.huwhy.bees.exception.MotanErrorMsgConstant;
//import cn.huwhy.bees.exception.MotanFrameworkException;
//import cn.huwhy.bees.filter.AccessLogFilter;
//import cn.huwhy.bees.filter.Filter;
//import cn.huwhy.bees.rpc.Protocol;
//import cn.huwhy.bees.rpc.Provider;
//import cn.huwhy.bees.rpc.Request;
//import cn.huwhy.bees.rpc.Response;
//import cn.huwhy.bees.rpc.URL;
//import cn.huwhy.bees.common.MotanConstants;
//import cn.huwhy.bees.common.URLParamType;
//import cn.huwhy.bees.core.extension.Activation;
//import cn.huwhy.bees.core.extension.ActivationComparator;
//import cn.huwhy.bees.core.extension.ExtensionLoader;
//import cn.huwhy.bees.core.extension.SpiMeta;
//import cn.huwhy.bees.rpc.Exporter;
//import cn.huwhy.bees.rpc.Referer;
//
///**
// *
// * Decorate the protocol, to add more features.
// *
// * @author fishermen
// * @version V1.0 created at: 2013-5-30
// */
//
//public class ProtocolFilterDecorator implements Protocol {
//
//    private Protocol protocol;
//
//    public ProtocolFilterDecorator(Protocol protocol) {
//        if (protocol == null) {
//            throw new MotanFrameworkException("Protocol is null when construct ProtocolFilterDecorator",
//                    MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR);
//        }
//        this.protocol = protocol;
//    }
//
//    @Override
//    public <T> Exporter<T> export(Provider<T> provider, URL url) {
//        return protocol.export(decorateWithFilter(provider, url), url);
//    }
//
//    @Override
//    public <T> Referer<T> refer(Class<T> clz, URL url, URL serviceUrl) {
//        return decorateWithFilter(protocol.refer(clz, url, serviceUrl), url);
//    }
//
//    public void destroy() {
//        protocol.destroy();
//    }
//
//    private <T> Referer<T> decorateWithFilter(Referer<T> referer, URL url) {
//        List<Filter> filters = getFilters(url, MotanConstants.NODE_TYPE_REFERER);
//        Referer<T> lastRef = referer;
//        for (Filter filter : filters) {
//            final Filter f = filter;
//            final Referer<T> lf = lastRef;
//            lastRef = new Referer<T>() {
//                @Override
//                public Response call(Request request) {
//                    Activation activation = f.getClass().getAnnotation(Activation.class);
//                    if (activation != null && !activation.retry() && request.getRetries() != 0) {
//                        return lf.call(request);
//                    }
//                    return f.filter(lf, request);
//                }
//
//                @Override
//                public String desc() {
//                    return lf.desc();
//                }
//
//                @Override
//                public void destroy() {
//                    lf.destroy();
//                }
//
//                @Override
//                public Class<T> getInterface() {
//                    return lf.getInterface();
//                }
//
//                @Override
//                public URL getUrl() {
//                    return lf.getUrl();
//                }
//
//                @Override
//                public void init() {
//                    lf.init();
//                }
//
//                @Override
//                public boolean isAvailable() {
//                    return lf.isAvailable();
//                }
//
//                @Override
//                public int activeRefererCount() {
//                    return lf.activeRefererCount();
//                }
//
//
//                @Override
//                public URL getServiceUrl() {
//                    return lf.getServiceUrl();
//                }
//            };
//        }
//        return lastRef;
//    }
//
//    private <T> Provider<T> decorateWithFilter(Provider<T> provider, URL url) {
//        List<Filter> filters = getFilters(url, MotanConstants.NODE_TYPE_SERVICE);
//        if (filters == null || filters.size() == 0) {
//            return provider;
//        }
//        Provider<T> lastProvider = provider;
//        for (Filter filter : filters) {
//            final Filter f = filter;
//            final Provider<T> lp = lastProvider;
//            lastProvider = new Provider<T>() {
//                @Override
//                public Response call(Request request) {
//                    return f.filter(lp, request);
//                }
//
//                @Override
//                public String desc() {
//                    return lp.desc();
//                }
//
//                @Override
//                public void destroy() {
//                    lp.destroy();
//                }
//
//                @Override
//                public Class<T> getInterface() {
//                    return lp.getInterface();
//                }
//
//                @Override
//                public URL getUrl() {
//                    return lp.getUrl();
//                }
//
//                @Override
//                public void init() {
//                    lp.init();
//                }
//
//                @Override
//                public boolean isAvailable() {
//                    return lp.isAvailable();
//                }
//            };
//        }
//        return lastProvider;
//    }
//
//    /**
//     * <pre>
//	 * 获取方式：
//	 * 1）先获取默认的filter列表；
//	 * 2）根据filter配置获取新的filters，并和默认的filter列表合并；
//	 * 3）再根据一些其他配置判断是否需要增加其他filter，如根据accessLog进行判断，是否需要增加accesslog
//	 * </pre>
//     *
//     * @param url
//     * @param key
//     * @return
//     */
//    private List<Filter> getFilters(URL url, String key) {
//
//        // load default filters
//        List<Filter> filters = new ArrayList<Filter>();
//        List<Filter> defaultFilters = ExtensionLoader.getExtensionLoader(Filter.class).getExtensions(key);
//        if (defaultFilters != null && defaultFilters.size() > 0) {
//            filters.addAll(defaultFilters);
//        }
//
//        // add filters via "filter" config
//        String filterStr = url.getParameter(URLParamType.filter.getName());
//        if (StringUtils.isNotBlank(filterStr)) {
//            String[] filterNames = MotanConstants.COMMA_SPLIT_PATTERN.split(filterStr);
//            for (String fn : filterNames) {
//                addIfAbsent(filters, fn);
//            }
//        }
//
//        // add filter via other configs, like accessLog and so on
//        boolean accessLog = url.getBooleanParameter(URLParamType.accessLog.getName(), URLParamType.accessLog.getBooleanValue());
//        if (accessLog) {
//            addIfAbsent(filters, AccessLogFilter.class.getAnnotation(SpiMeta.class).name());
//        }
//
//        // sort the filters
//        Collections.sort(filters, new ActivationComparator<Filter>());
//        Collections.reverse(filters);
//        return filters;
//    }
//
//    private void addIfAbsent(List<Filter> filters, String extensionName) {
//        if (StringUtils.isBlank(extensionName)) {
//            return;
//        }
//
//        Filter extFilter = ExtensionLoader.getExtensionLoader(Filter.class).getExtension(extensionName);
//        if (extFilter == null) {
//            return;
//        }
//
//        boolean exists = false;
//        for (Filter f : filters) {
//            if (f.getClass() == extFilter.getClass()) {
//                exists = true;
//                break;
//            }
//        }
//        if (!exists) {
//            filters.add(extFilter);
//        }
//
//    }
//}
